"""元数据生成命令模块"""

import argparse
from pathlib import Path
from typing import Optional, Callable
from src.core.command import Command
from src.commands.gen_config import GenConfigCommand
from src.commands.merge_config import MergeConfigCommand
from src.base.registry import bera
from src.base.sql_file_utils import SQLFileUtils
from src.base.project_config import ProjectConfig
from datetime import datetime

class GenMetaCommand(Command):
    """元数据生成命令"""

    def __init__(self):
        super().__init__()
        self.name = "gen-meta"
        self.group = "配置管理"
        self.help = "生成表的元数据配置文件"
        self.description = """
        生成表的元数据配置文件。该命令会:
        1. 调用 gen-config 生成配置文件
        2. 合并配置文件生成元数据
        3. 支持自定义输出目录和强制重新生成
        """

    def add_arguments(self, parser: argparse.ArgumentParser) -> None:
        """添加命令参数"""
        # 添加通用参数
        SQLFileUtils.add_arguments(parser)

        # 添加命令特有参数
        parser.add_argument('--force', action='store_true', help='强制重新生成配置文件')

    def execute(self, args: argparse.Namespace, callback: Optional[Callable[[], None]] = None) -> None:
        """执行命令"""
        try:
            bera.logger.info("开始执行gen-meta命令")

            # 先初始化项目配置
            ProjectConfig.init(args.project_dir)

            # 先添加项目配置的sql-dir到搜索路径(优先级较低)
            sql_dir = str(ProjectConfig.get_sql_dir())
            bera.logger.debug(f"添加项目配置的SQL目录到搜索路径: {sql_dir}")
            SQLFileUtils.add_search_path(sql_dir)

            # 后执行callback,让它添加的搜索路径优先级更高
            if callback:
                callback()

            # 使用统一的输入模式处理
            SQLFileUtils.execute_file_processing(args, self._process_sql_file)

            bera.logger.info("gen-meta命令执行完成")
        except Exception as e:
            bera.logger.error(f"gen-meta命令执行失败: {str(e)}")
            if args.verbose:
                import traceback
                traceback.print_exc()
            raise

    def _process_sql_file(self, filepath: str, args: argparse.Namespace) -> None:
        """处理单个文件

        Args:
            filepath: SQL文件路径
            args: 命令行参数
        """
        try:
            # 从文件路径中提取表名
            table_name = Path(filepath).stem
            bera.logger.info(f"处理表: {table_name}")

            # 获取目录路径
            config_dir = SQLFileUtils.get_output_merge_dir(table_name)
            SQLFileUtils.ensure_directory(config_dir)
            bera.logger.debug(f"配置目录: {config_dir}")

            # 调用gen-config生成配置文件
            bera.logger.info("开始生成配置文件...")
            self._generate_configs(table_name, filepath, config_dir, args)

            # 合并配置文件生成元数据
            bera.logger.info("开始生成元数据...")
            self._generate_meta(table_name, config_dir, args)

        except Exception as e:
            bera.logger.error(f"处理表失败: {table_name}")
            if args.verbose:
                import traceback
                traceback.print_exc()
            SQLFileUtils.handle_file_error(e, Path(filepath), table_name)

    def _generate_configs(self, table_name: str, filepath: str, config_dir: Path, args: argparse.Namespace) -> None:
        """生成配置文件

        Args:
            table_name: 表名
            filepath: SQL文件路径
            config_dir: 配置目录
            args: 命令行参数
        """
        try:
            # 调用gen-config生成配置文件
            gen_cmd = GenConfigCommand()
            gen_args = self._create_gen_config_args(filepath, config_dir, args)
            gen_cmd.execute(gen_args)

            # 复制sql.json到配置目录
            sql_json_dir = ProjectConfig.get_sql_dir()
            sql_json_file = sql_json_dir / f"{table_name}.sql.json"
            if sql_json_file.exists():
                target_file = config_dir / "sql.json"
                SQLFileUtils.copy_sql_file(sql_json_file, target_file, args.verbose)
                bera.logger.debug(f"复制SQL描述文件: {sql_json_file} -> {target_file}")

        except Exception as e:
            bera.logger.error(f"生成配置文件失败: {str(e)}")
            raise

    def _generate_meta(self, table_name: str, config_dir: Path, args: argparse.Namespace) -> None:
        """生成元数据文件

        Args:
            table_name: 表名
            config_dir: 配置目录
            args: 命令行参数
        """
        try:
            # 获取元数据文件路径
            meta_file = SQLFileUtils.get_output_table_dir(table_name) / "meta.auto.json"

            # 调用merge-config合并配置文件
            merge_cmd = MergeConfigCommand()
            merge_args = self._create_merge_config_args(config_dir, meta_file, args)
            merge_cmd.execute(merge_args)

            # 后处理: 确保所有配置都有mark属性
            self._post_process_meta(meta_file)

            bera.logger.info(f"生成元数据文件: {meta_file}")

        except Exception as e:
            bera.logger.error(f"生成元数据失败: {str(e)}")
            raise

    def _post_process_meta(self, meta_file: Path) -> None:
        """后处理元数据文件,确保所有配置都有mark属性

        Args:
            meta_file: 元数据文件路径
        """
        try:
            # 读取元数据
            meta_data = SQLFileUtils.read_json_file(meta_file)

            # 处理表级配置
            if "table" in meta_data:
                if "mark" not in meta_data["table"]:
                    meta_data["table"]["mark"] = {}

                # 添加项目信息
                project_info = ProjectConfig.get_project_info()
                meta_data["table"]["mark"].update({
                    "version": project_info["version"],
                    "current_date": datetime.now().strftime("%Y-%m-%d"),
                    "company": project_info["company"],
                    "author": project_info["author"],
                    "website": project_info["website"],
                    "copyright": project_info["copyright"]
                })

            # 处理字段级配置
            if "columns" in meta_data:
                for field_name, field_config in meta_data["columns"].items():
                    if "mark" not in field_config:
                        field_config["mark"] = {}

            # 写回文件
            SQLFileUtils.write_json_file(meta_file, meta_data)

        except Exception as e:
            bera.logger.error(f"后处理元数据失败: {str(e)}")
            raise

    def _create_gen_config_args(self, filepath: str, config_dir: Path, args: argparse.Namespace) -> argparse.Namespace:
        """创建gen-config命令参数"""
        return argparse.Namespace(
            filename=None,
            filepath=filepath,
            directory=None,
            output=str(config_dir),
            verbose=args.verbose,
            force=args.force,
            project_dir=args.project_dir
        )

    def _create_merge_config_args(self, config_dir: Path, meta_file: Path, args: argparse.Namespace) -> argparse.Namespace:
        """创建merge-config命令参数"""
        return argparse.Namespace(
            dir=str(config_dir),
            target=str(meta_file),
            verbose=args.verbose,
            indent=2,
            dry_run=False,
            project_dir=args.project_dir
        )